class ContentScript {
  constructor() {
    this.elementController = null;
    this.currentUrl = window.location.href;
    this.appliedRules = new Map();
    this.observer = null;
    this.debounceTimer = null;
    this.DEBOUNCE_DELAY = 300;
    this.isInitialized = false;
    this.init();
  }

  async init() {
    try {
      // Initialize storage
      await StorageManager.initialize();
      
      // Initialize element controller
      this.elementController = new ElementController();
      
      // Apply rules for current page with delay to ensure DOM is ready
      setTimeout(async () => {
        await this.applyCurrentPageRules();
      }, 500);
      
      // Setup DOM monitoring
      this.setupDOMMonitoring();
      
      // Setup URL change monitoring (for SPAs)
      this.setupURLChangeMonitoring();
      
      // Setup message listener
      this.setupMessageListener();
      
      // Listen for storage changes
      this.setupStorageListener();
      
      this.isInitialized = true;
      console.log('Element Controller: Content script initialized');
    } catch (error) {
      console.error('Element Controller: Failed to initialize content script:', error);
    }
  }

  async applyCurrentPageRules() {
    try {
      const rules = await StorageManager.getRules();
      
      if (!rules || !rules.urlRules || rules.urlRules.length === 0) {
        return;
      }
      
      const matchingRules = URLMatcher.getMatchingElementRules(this.currentUrl, rules);
      
      if (matchingRules.length === 0) {
        return;
      }
      
      // Clear previously applied rules
      this.clearAllAppliedRules();
      
      // Apply new rules
      let appliedCount = 0;
      for (const rule of matchingRules) {
        const result = this.elementController.applyElementRule(rule);
        if (result.success) {
          this.appliedRules.set(rule.id, {
            ...rule,
            appliedAt: Date.now(),
            result: result
          });
          appliedCount++;
        } else {
          console.warn(`Element Controller: Failed to apply rule ${rule.id}:`, result.error);
        }
      }
    } catch (error) {
      console.error('Element Controller: Failed to apply page rules:', error);
    }
  }

  setupDOMMonitoring() {
    if (this.observer) {
      this.observer.disconnect();
    }
    
    this.observer = new MutationObserver((mutations) => {
      this.handleDOMChanges(mutations);
    });
    
    const config = {
      childList: true,
      subtree: true,
      attributes: true,
      attributeFilter: ['class', 'id', 'style'],
      characterData: false
    };
    
    this.observer.observe(document.body, config);
    console.log('Element Controller: DOM monitoring started');
  }

  handleDOMChanges(mutations) {
    // Debounce DOM change handling to avoid excessive processing
    if (this.debounceTimer) {
      clearTimeout(this.debounceTimer);
    }
    
    this.debounceTimer = setTimeout(() => {
      this.processDOMChanges(mutations);
    }, this.DEBOUNCE_DELAY);
  }

  processDOMChanges(mutations) {
    let hasSignificantChanges = false;
    
    // Check if mutations include significant changes
    for (const mutation of mutations) {
      if (mutation.type === 'childList' && (mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0)) {
        // Check if added/removed nodes are elements (not text nodes)
        const hasElementChanges = Array.from(mutation.addedNodes).some(node => node.nodeType === Node.ELEMENT_NODE) ||
                                 Array.from(mutation.removedNodes).some(node => node.nodeType === Node.ELEMENT_NODE);
        
        if (hasElementChanges) {
          hasSignificantChanges = true;
          break;
        }
      } else if (mutation.type === 'attributes') {
        // Attribute changes might affect element selection
        hasSignificantChanges = true;
        break;
      }
    }
    
    if (hasSignificantChanges) {
      this.reapplyRules();
    }
  }

  reapplyRules() {
    // Use requestIdleCallback for better performance
    if (window.requestIdleCallback) {
      window.requestIdleCallback(() => {
        this.performRuleReapplication();
      }, { timeout: 1000 });
    } else {
      // Fallback for browsers without requestIdleCallback
      setTimeout(() => {
        this.performRuleReapplication();
      }, 50);
    }
  }

  performRuleReapplication() {
    try {
      // Reapply all currently applied rules
      for (const [ruleId, appliedRule] of this.appliedRules.entries()) {
        const result = this.elementController.applyElementRule(appliedRule);
        if (result.success) {
          // Update the applied rule info
          this.appliedRules.set(ruleId, {
            ...appliedRule,
            result: result,
            lastReapplied: Date.now()
          });
        }
      }
    } catch (error) {
      console.error('Element Controller: Failed to reapply rules:', error);
    }
  }

  setupURLChangeMonitoring() {
    // Monitor URL changes for SPAs
    let lastUrl = this.currentUrl;
    
    const checkUrlChange = () => {
      const currentUrl = window.location.href;
      if (currentUrl !== lastUrl) {
        lastUrl = currentUrl;
        this.currentUrl = currentUrl;
        console.log('Element Controller: URL changed to', currentUrl);
        
        // Reapply rules for new URL
        this.applyCurrentPageRules();
      }
    };
    
    // Use multiple methods to detect URL changes
    
    // 1. PopState event (for back/forward navigation)
    window.addEventListener('popstate', checkUrlChange);
    
    // 2. HashChange event
    window.addEventListener('hashchange', checkUrlChange);
    
    // 3. Periodic URL checking (fallback for programmatic navigation)
    setInterval(checkUrlChange, 1000);
    
    // 4. Override pushState and replaceState
    const originalPushState = history.pushState;
    const originalReplaceState = history.replaceState;
    
    history.pushState = function(...args) {
      originalPushState.apply(history, args);
      setTimeout(checkUrlChange, 0);
    };
    
    history.replaceState = function(...args) {
      originalReplaceState.apply(history, args);
      setTimeout(checkUrlChange, 0);
    };
    
    console.log('Element Controller: URL change monitoring setup complete');
  }

  setupMessageListener() {
    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      this.handleMessage(message, sender, sendResponse);
      return true; // Keep message channel open for async response
    });
  }

  async handleMessage(message, sender, sendResponse) {
    try {
      switch (message.action) {
        case 'testSelector':
          const testResult = this.elementController.testSelector(message.selector);
          sendResponse(testResult);
          break;
          
        case 'highlightElements':
          const highlightResult = this.elementController.highlightElements(message.selector, 3000);
          sendResponse(highlightResult);
          break;
          
        case 'getMatchCount':
          const matchResult = this.elementController.getMatchCount(message.selector);
          sendResponse(matchResult);
          break;
          
        case 'applyRule':
          const applyResult = this.elementController.applyElementRule(message.rule);
          if (applyResult.success) {
            this.appliedRules.set(message.rule.id, {
              ...message.rule,
              appliedAt: Date.now(),
              result: applyResult
            });
          }
          sendResponse(applyResult);
          break;
          
        case 'removeRule':
          const removeResult = this.elementController.removeElementRule(message.ruleId);
          if (removeResult.success) {
            this.appliedRules.delete(message.ruleId);
          }
          sendResponse(removeResult);
          break;
          
        case 'getAppliedRules':
          const appliedRulesInfo = this.elementController.getAppliedRulesInfo();
          sendResponse({ rules: appliedRulesInfo });
          break;
          
        case 'reapplyAllRules':
          await this.applyCurrentPageRules();
          sendResponse({ success: true });
          break;
          
        case 'forceApplyRule':
          const forceResult = this.elementController.applyElementRule(message.rule);
          if (forceResult.success) {
            this.elementController.injectCSS();
          }
          sendResponse(forceResult);
          break;
          
        case 'ping':
          sendResponse({ success: true, url: this.currentUrl });
          break;
          
        default:
          sendResponse({ success: false, error: `Unknown action: ${message.action}` });
      }
    } catch (error) {
      console.error('Element Controller: Error handling message:', error);
      sendResponse({ success: false, error: error.message });
    }
  }

  setupStorageListener() {
    StorageManager.onChanged(async (newRules, oldRules) => {
      try {
        await this.applyCurrentPageRules();
      } catch (error) {
        console.error('Element Controller: Error in storage change handler:', error);
      }
    });
  }

  clearAllAppliedRules() {
    // Clear all applied rules from element controller
    this.elementController.clearAllRules();
    
    // Clear our tracking
    this.appliedRules.clear();
  }

  destroy() {
    if (this.observer) {
      this.observer.disconnect();
      this.observer = null;
    }
    
    if (this.debounceTimer) {
      clearTimeout(this.debounceTimer);
      this.debounceTimer = null;
    }
    
    this.clearAllAppliedRules();
    
    console.log('Element Controller: Content script destroyed');
  }

  // Debug helpers
  getDebugInfo() {
    return {
      isInitialized: this.isInitialized,
      currentUrl: this.currentUrl,
      appliedRulesCount: this.appliedRules.size,
      appliedRules: Array.from(this.appliedRules.entries()),
      hasObserver: !!this.observer,
      elementControllerInfo: this.elementController?.getAppliedRulesInfo() || []
    };
  }
}

// Global error handler for the content script
window.addEventListener('error', (event) => {
  if (event.error?.message?.includes('Element Controller')) {
    console.error('Element Controller: Unhandled error:', event.error);
  }
});

// 确保页面完全加载后再初始化
function initializeContentScript() {
  // 避免重复初始化
  if (window.elementControllerContent) {
    return;
  }
  
  window.elementControllerContent = new ContentScript();
}

if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', initializeContentScript);
} else if (document.readyState === 'interactive') {
  setTimeout(initializeContentScript, 100);
} else {
  initializeContentScript();
}

// Handle page unload
window.addEventListener('beforeunload', () => {
  if (window.elementControllerContent) {
    window.elementControllerContent.destroy();
  }
});

// Expose debug function to console
window.getElementControllerDebugInfo = () => {
  return window.elementControllerContent?.getDebugInfo() || 'Content script not initialized';
};